#include "InterpreteXml.hpp"

#include "DescriptionFichier.hpp"

#include "FournisseurDescription.hpp"

#include "StructureDonnees.hpp"

#include <QtCore/QIODevice>

#include <QtXml/QXmlStreamReader>

#include <iostream>

using namespace std;

InterpreteXml::InterpreteXml( const QString& typeFichier, QObject * parent )
  : QObject( parent ), ContenuAttendu( 0 ), Parseur( 0 ),
    AfficheMessageDebuging( false )
{
  ContenuAttendu = obtenirDescription( typeFichier );

  if ( ContenuAttendu == 0 )
    {
      cerr << "Impossible de récupérer la description du fichier à lire!"
	   << endl;
      exit( 1 );
    }

  ContenuAttendu -> affichageCompletContenu();
}

InterpreteXml::~InterpreteXml()
{}

void InterpreteXml::setEntree( QIODevice * entree )
{
  if ( Parseur != 0 )
    {
      delete Parseur;
      Parseur = 0;
    }

  Parseur = new QXmlStreamReader( entree );
}

unsigned InterpreteXml::lireEntree( StructureDonnees& donnees )
{
  if ( Parseur == 0 )
    {
      cerr << "Le parseur n'est pas initialisé" << endl;
      return 5;
    }

  QXmlStreamAttributes attributs;

  const QSet< QString > * balisesConsideres = ContenuAttendu -> listeBalises();
  const QHash< QString, QStringList > * attributsConsideres =
    ContenuAttendu -> listeAttributs();
  QStringList reference;
  
  QString clef, tmpNomAttribut;
  QHash< QString, QString > valeurs;

  QString ErreurStr( "err" );
  QString VerrouStr( "locked" );

  while ( ! Parseur -> atEnd() )
    {
      Parseur -> readNext();

      if ( Parseur -> isStartElement() )
	{
	  clef = Parseur -> name() . toString();

	  if ( AfficheMessageDebuging )
	    cout << "Lecture de '" << clef . toUtf8() . constData()
		 << "'" << endl;

	  if ( clef == ErreurStr )
	    return traitementException();
	  else if( clef == VerrouStr )
	    {
	      cout << "Le site est temporairement inaccessible pour "
		   << "l'ouverture du fuseau horaire." << endl;
	      return 20u;
	    }

	  if ( ! balisesConsideres -> contains( clef ) )
	    continue;

	  attributs = Parseur -> attributes();
	  if ( attributs . size() == 0 &&
	       (*attributsConsideres)[ clef ] . size() != 0 )
	    cerr << "Problème : aucun attribut récupéré alors qu'on en attend "
		 << (*attributsConsideres)[ clef ] . size() << endl;
	  else
	    {
	      reference = (*attributsConsideres)[ clef ];

	      foreach ( tmpNomAttribut, reference )
		{
		  if ( attributs . hasAttribute( tmpNomAttribut ) )
		    {
		      valeurs . insert( tmpNomAttribut,
					attributs . value( tmpNomAttribut ) . toString() );
		      if ( AfficheMessageDebuging )
			cout << "Ajout de '"
			     << tmpNomAttribut . toUtf8() . constData()
			     << "'" << endl;
		    }
		}
	    }

	  donnees . insert( clef, valeurs );

	  valeurs.clear();
	}
    }

  if ( Parseur -> hasError() )
    {
      cerr << Parseur -> errorString() . toUtf8() . constData() << endl;
      cerr << "A la ligne " << Parseur -> lineNumber() << ", colonne "
	   << Parseur -> columnNumber() << endl;
      return static_cast< unsigned >( Parseur -> error() );
    }

  return 0;
}

unsigned InterpreteXml::traitementException()
{
  QXmlStreamAttributes attributs( Parseur -> attributes() );

  if ( ! attributs . hasAttribute( QString( "error" ) ) )
    {
      cerr << "Erreur inconnue!" << endl;
      return -1u;
    }

  QString texteErreur( attributs . value( QString( "error" ) ) . toString() );

  if ( texteErreur . indexOf( "user" ) != -1 )
    cerr << "Utilisateur inconnu" << endl;
  else if ( texteErreur . indexOf( "syndicate" ) != -1 )
    cerr << "Syndicat inconnu" << endl;
  else if ( texteErreur . indexOf( "API" ) != -1 )
    cerr << "Accès API non autorisé pour cet utilisateur" << endl;
  else if ( texteErreur . indexOf( "Bad" ) != -1 )
    cerr << "Erreur de mot de passe API" << endl;

  return 30u;
}
